﻿#include "precomp.h"
#include "jruledict.h"
#include <QDomElement>

// - class JRuleDictPrivate -

class JRuleDictPrivate
{
    J_DECLARE_PUBLIC(JRuleDict)
    public:
        JRuleDictPrivate(JRuleDict *parent)
      : q_ptr(parent)
    {

    }

    bool openDocument();
    bool saveDocument(bool reload = true);
    QDomElement findTableNode(bool *added = 0);     // find global table node
    QDomElement findTableNode(QDomElement emRoot, bool *added = 0);   // find global table node
    QDomElement findTableNode(const QString &JX, bool *added = 0);  //
    QDomElement findTableNode(QDomElement emRoot, const QString &JX, bool *added = 0);  //
    QDomElement findItemNode(QDomElement emTable, const QString &name, bool *added = 0);
    QDomElement findItemNode(const QString &name, bool *added = 0);
    QDomElement findItemNode(const QString &JX, const QString &name, bool *added = 0);
    QDomElement findItemNode(QDomElement emRoot, const QString &JX, const QString &name, bool *added = 0);
    bool setDomElementText(QDomElement element, const QString &text);

    bool addSymbol(QDomElement emTable, const QString &name, const QStringList &symbols);
    bool removeSymbol(QDomElement eemTable, const QString &name, const QStringList &symbols);
    bool replaceSymbol(QDomElement emItem, const QString &oldSymbol, const QString &newSymbol);

private:
    QString filePath;
    QDomDocument document;
    QMap<QString/*JX*/, QMap<QString/*name*/, QStringList/*symbols*/> > mapRule;
};

bool JRuleDictPrivate::openDocument()
{
    // 清除旧数据
    document.clear();

    // 检测文件是否存在
    if (!QFile::exists(filePath)) {
        return false;
    }

    // 打开规则文件
    QFile file(filePath);
    if (!file.open(QFile::ReadOnly)) {
        return false;  // open failure
    }

    QString errorMsg;
    int errorLine;
    int errorColumn;

    // 设置文档内容
    if (!document.setContent(&file, &errorMsg, &errorLine, &errorColumn)) {
        qCritical() << QStringLiteral("规则文件%1导入失败！(msg: %2 in [%3, %4]").arg(filePath)
                       .arg(errorMsg).arg(errorLine).arg(errorColumn);
        return false;
    }

    return true;
}

bool JRuleDictPrivate::saveDocument(bool reload)
{
    // 检测参数有效性
    if (filePath.isEmpty() || document.isNull()) {
        return false;
    }

    // 创建并打开目标文件
    QFile out(filePath);
    if (!out.open(QFile::WriteOnly | QFile::Text)) {
        return false;
    }

    // 将文档内容导入打开的目标文件中
    QTextStream ts(&out);
    document.save(ts, 4);

    // 重新加载规则文件
    if (reload) {
        Q_Q(JRuleDict);
        if (!q->loadRuleFile(filePath)) {
            return false;
        }
    }

    return true;
}

QDomElement JRuleDictPrivate::findTableNode(bool *added)
{
    // 初始化输出参数
    if (added) {
        *added = false;
    }

    // 检测参数有有效性
    if (document.isNull()) {
        return QDomElement();
    }

    // 查找规则节点
    return findTableNode(document.documentElement(), added);
}

QDomElement JRuleDictPrivate::findTableNode(QDomElement emRoot, bool *added)
{
    // 初始化输出参数
    if (added) {
        *added = false;
    }

    // 检测参数有有效性
    if (emRoot.isNull()) {
        return QDomElement();
    }

    QDomElement emTable;

    // 查找全局规则节点（条件：无机型属性或机型属性值为空值）
    for (emTable = emRoot.firstChildElement("table");
         !emTable.isNull();
         emTable = emTable.nextSiblingElement("table")) {
        if (!emTable.hasAttribute("JX")
                || emTable.attribute("JX").isEmpty()) {
            break;      // 找到
        }
    }

    // 未找到。根据条件是否自动添加一个全局规则节点
    if (emTable.isNull() && added) {
        emTable = emRoot.insertBefore(document.createElement("table"),
                                      emRoot.firstChild()).toElement();
        if (!emTable.isNull()) {
            *added = true;     // 增加成功
        }
    }

    return emTable;
}

QDomElement JRuleDictPrivate::findTableNode(const QString &JX, bool *added)
{
    // 初始化输出参数
    if (added) {
        *added = false;
    }

    // 检测参数有有效性
    if (document.isNull()) {
        return QDomElement();
    }

    // 查找规则节点
    return findTableNode(document.documentElement(), JX, added);
}

QDomElement JRuleDictPrivate::findTableNode(QDomElement emRoot, const QString &JX, bool *added)
{
    // 初始化输出参数
    if (added) {
        *added = false;
    }

    // 检测参数有有效性
    if (emRoot.isNull() || JX.isEmpty()) {
        return QDomElement();
    }

    QDomElement emTable;

    // 查找指定机型的规则节点
    for (emTable = emRoot.firstChildElement("table");
         !emTable.isNull();
         emTable = emTable.nextSiblingElement("table")) {
        if (emTable.hasAttribute("JX")
                && emTable.attribute("JX") == JX) {
            break;      // 找到
        }
    }

    // 未找到。根据条件是否自动添加一个指定机型的规则节点
    if (emTable.isNull() && added) {
        emTable = emRoot.insertAfter(document.createElement("table"),
                                     emRoot.lastChild()).toElement();
        if (!emTable.isNull()) {
            *added = true;     // 增加成功
            // 设置机型节点属性：机型名称
            emTable.setAttribute("JX", JX);
        }
    }

    return emTable;
}

QDomElement JRuleDictPrivate::findItemNode(QDomElement emTable, const QString &name, bool *added)
{
    // 初始化输出参数
    if (added) {
        *added = false;
    }

    // 检测参数有有效性
    if (emTable.isNull() || name.isEmpty()) {
        return QDomElement();
    }

    QDomElement emItem;

    // 查找指定机型的规则节点
    for (emItem = emTable.firstChildElement("item");
         !emItem.isNull();
         emItem = emItem.nextSiblingElement("item")) {
        if (emItem.hasAttribute("name")
                && emItem.attribute("name") == name) {
            break;      // 找到
        }
    }

    // 未找到。根据条件是否自动添加一个指定别名的规则节点
    if (emItem.isNull() && added) {
        emItem = emTable.insertAfter(document.createElement("item"),
                                     emTable.lastChild()).toElement();
        if (!emItem.isNull()) {
            *added = true;      // 增加成功
            // 设置别名节点属性：别名
            emItem.setAttribute("name", name);
        }
    }

    return emItem;
}

QDomElement JRuleDictPrivate::findItemNode(const QString &name, bool *added)
{
    // 初始化输出参数
    if (added) {
        *added = false;
    }

    // 检测参数有有效性
    if (name.isEmpty()) {
        return QDomElement();
    }

    // 查找全局规则节点
    QDomElement emTable = findTableNode(added);
    if (emTable.isNull()) {
        return QDomElement();   // 未找到
    }

    // 查找别名节点
    return findItemNode(emTable, name, added);
}

QDomElement JRuleDictPrivate::findItemNode(const QString &JX, const QString &name, bool *added)
{
    // 初始化输出参数
    if (added) {
        *added = false;
    }

    // 检测参数有有效性
    if (JX.isEmpty() || name.isEmpty()) {
        return QDomElement();
    }

    // 查找全局规则节点
    QDomElement emTable = findTableNode(JX, added);
    if (emTable.isNull()) {
        return QDomElement();   // 未找到
    }

    // 查找别名节点
    return findItemNode(emTable, name, added);
}

QDomElement JRuleDictPrivate::findItemNode(QDomElement emRoot, const QString &JX,
                                           const QString &name, bool *added)
{
    // 查找规则节点
    QDomElement emTable = findTableNode(emRoot, JX, added);
    if (emTable.isNull()) {
        return QDomElement();   // 未找到
    }

    // 查找映射节点
    return findItemNode(emTable, name, added);
}

bool JRuleDictPrivate::setDomElementText(QDomElement element, const QString &text)
{
    if (element.isNull()) {
        return false;
    }

    if (!element.hasChildNodes()) {
        element.appendChild(document.createTextNode(text));
    } else {
        element.firstChild().setNodeValue(text);
    }

    return true;
}

bool JRuleDictPrivate::addSymbol(QDomElement emTable, const QString &name, const QStringList &symbols)
{
    //  参数有效性检测
    if (emTable.isNull() || name.isEmpty() || symbols.isEmpty()) {
        return false;   // 参数无效
    }

    // 查找别名是否已存在
    QDomElement emItem;
    for (emItem = emTable.firstChildElement("item");
         !emItem.isNull();
         emItem = emItem.nextSiblingElement("item")) {
        if (!emItem.hasAttribute("name")) {
            continue;   // 没有别名属性，视为无效数据
        }
        // 匹配别名
        if (emItem.attribute("name") == name) {
            break;      // 找到
        }
    }

    if (emItem.isNull()) {  // 未找到，则增加一条别名映射节点
        QDomElement emNewItem = document.createElement("item");
        emNewItem.setAttribute("name", name);
        emNewItem.appendChild(document.createTextNode(symbols.join(',')));
        emTable.appendChild(emNewItem);
    } else {
        // 追加变量
        QStringList oldSymbols = emItem.text().trimmed().split(',', QString::SkipEmptyParts);
        oldSymbols.removeAll(",");
        // 去掉空格
        QMutableStringListIterator iterOldSymbols(oldSymbols);
        while (iterOldSymbols.hasNext()) {
            QString &oldSymbol = iterOldSymbols.next();
            oldSymbol = oldSymbol.trimmed();
        }
        foreach (const QString &symbol, symbols) {
            if (!oldSymbols.contains(symbol)) {
                oldSymbols.append(symbol);
            }
        }
        setDomElementText(emItem, oldSymbols.join(','));
    }

    // 保存更改
    if (!saveDocument(true)) {
        return false;
    }

    return true;
}

bool JRuleDictPrivate::removeSymbol(QDomElement emTable, const QString &name, const QStringList &symbols)
{
    //  参数有效性检测
    if (emTable.isNull() || name.isEmpty() || symbols.isEmpty()) {
        return false;   // 参数无效
    }

    // 查找别名是否已存在
    QDomElement emItem;
    for (emItem = emTable.firstChildElement("item");
         !emItem.isNull();
         emItem = emItem.nextSiblingElement("item")) {
        if (!emItem.hasAttribute("name")) {
            continue;   // 没有别名属性，视为无效数据
        }
        // 匹配别名
        if (emItem.attribute("name") == name) {
            break;      // 找到
        }
    }

    if (emItem.isNull()) {  // 未找到，则返回
        return true;
    }

    // 删除变量
    QStringList oldSymbols = emItem.text().trimmed().split(',', QString::SkipEmptyParts);
    oldSymbols.removeAll(",");
    // 去掉空格
    QMutableStringListIterator iterOldSymbols(oldSymbols);
    while (iterOldSymbols.hasNext()) {
        QString &oldSymbol = iterOldSymbols.next();
        oldSymbol = oldSymbol.trimmed();
    }
    foreach (const QString &symbol, symbols) {
        if (oldSymbols.contains(symbol)) {
            oldSymbols.removeAll(symbol);
        }
    }
    setDomElementText(emItem, oldSymbols.join(','));

    // 保存更改
    if (!saveDocument(true)) {
        return false;
    }

    return true;
}

bool JRuleDictPrivate::replaceSymbol(QDomElement emItem, const QString &oldSymbol, const QString &newSymbol)
{
    //  参数有效性检测
    if (emItem.isNull() || oldSymbol.isEmpty() || newSymbol.isEmpty()) {
        return false;   // 参数无效
    }

    // 获取别名中的所有变量名
    QStringList symbols = emItem.text().split(',', QString::SkipEmptyParts);

    // 去掉空格
    QMutableStringListIterator iterSymbols(symbols);
    while (iterSymbols.hasNext()) {
        QString &symbol = iterSymbols.next();
        symbol = symbol.trimmed();
    }

    // 查询是否存在原有变量名
    if (!symbols.contains(oldSymbol)) {
        return false;
    }

    // 修改变量名称
    setDomElementText(emItem, symbols.join(',').replace(oldSymbol, newSymbol));

    // 保存更改
    if (!saveDocument(true)) {
        return false;
    }

    return true;
}

// - class JAliasDict -

J_IMPLEMENT_SINGLE_INSTANCE(JRuleDict)

JRuleDict::JRuleDict() :
    d_ptr(new JRuleDictPrivate(this))
{

}

JRuleDict::~JRuleDict()
{
    delete d_ptr;
}

bool JRuleDict::isValid() const
{
    Q_D(const JRuleDict);
    return !d->mapRule.isEmpty();
}

bool JRuleDict::loadRuleFile(const QString &filePath)
{
    Q_D(JRuleDict);

    d->filePath = filePath;
    d->document.clear();
    d->mapRule.clear();

    // 打开规则文件
    if (!d->openDocument()) {
        return false;
    }

    // 获取根节点
    QDomElement emRoot = d->document.documentElement();
    if (emRoot.isNull()) {
        qCritical() << QStringLiteral("规则文件%1没有根节点！").arg(d->filePath);
        return false;
    }

    // 分机型解析规则
    for (QDomElement emTable = emRoot.firstChildElement("table");
         !emTable.isNull();
         emTable = emTable.nextSiblingElement("table")) {
        // 获取机型信息（如果机型为空（或不存在），则视为全局规则（以空字符串作为映射键值））
        QString JX = emTable.attribute("JX");
        // 解析每条规则映射
        QMap<QString, QStringList> mapRule;
        for (QDomElement emItem = emTable.firstChildElement("item");
             !emItem.isNull();
             emItem = emItem.nextSiblingElement("item")) {
            // 获取名称
            if (!emItem.hasAttribute("name")) {
                continue;   // 不存在name属性，则视为无效数据
            }
            QString name = emItem.attribute("name");
            if (name.isEmpty()) {
                continue;   // name属性值为空，则视为无效数据
            }
            // 解析变量列表
            QStringList symbols = emItem.text().trimmed().split(',', QString::SkipEmptyParts);
            // 去掉空格
            QMutableStringListIterator iterSymbols(symbols);
            while (iterSymbols.hasNext()) {
                QString &symbol = iterSymbols.next();
                symbol = symbol.trimmed();
            }
            mapRule[name] = symbols;
        }
        // 保存机型-规则映射
        d->mapRule[JX] = mapRule;
    }

    return true;
}

bool JRuleDict::addJX(const QString &JX)
{
    Q_D(JRuleDict);

    //  打开规则文件
    if (!d->openDocument()) {
        return false;
    }

    // 查找是已存在指定机型节点，不存在则自动添加
    bool add = false;
    QDomElement emTable = d->findTableNode(JX, &add);
    if (emTable.isNull() || !add) {
        return false;       // 已存在
    }

    // 保存更改
    if (!d->saveDocument(true)) {
        return false;
    }

    return true;
}

bool JRuleDict::removeJX(const QString &JX)
{
    Q_D(JRuleDict);

    //  打开规则文件
    if (!d->openDocument()) {
        return false;
    }

    // 查找是已存在相同机型
    QDomElement emTable = d->findTableNode(JX);
    if (emTable.isNull()) {
        return true;       // 不存在
    }

    // 删除机型节点
    d->document.documentElement().removeChild(emTable);

    // 保存更改
    if (!d->saveDocument(true)) {
        return false;
    }

    return true;
}

bool JRuleDict::addSymbol(const QString &name, const QStringList &symbols)
{
    Q_D(JRuleDict);

    //  打开规则文件
    if (!d->openDocument()) {
        return false;
    }

    // 检测规则文件中是否有全局规则，没有则添加
    bool add = false;
    QDomElement emTable = d->findTableNode(&add);
    if (emTable.isNull()) {
        return false;   // 未找到
    }

    return d->addSymbol(emTable, name, symbols);
}

bool JRuleDict::addSymbol(const QString &JX, const QString &name, const QStringList &symbols)
{
    Q_D(JRuleDict);

    //  打开规则文件
    if (!d->openDocument()) {
        return false;
    }

    // 检测规则文件中是否有全局规则，没有则添加
    bool add = false;
    QDomElement emTable = d->findTableNode(JX, &add);
    if (emTable.isNull()) {
        return false;   // 未找到
    }

    return d->addSymbol(emTable, name, symbols);
}

bool JRuleDict::removeSymbol(const QString &name, const QStringList &symbols)
{
    Q_D(JRuleDict);

    //  打开规则文件
    if (!d->openDocument()) {
        return false;
    }

    // 检测规则文件中是否有全局规则
    QDomElement emTable = d->findTableNode(0);
    if (emTable.isNull()) {
        return false;   // 未找到
    }

    return d->removeSymbol(emTable, name, symbols);
}

bool JRuleDict::removeSymbol(const QString &JX, const QString &name, const QStringList &symbols)
{
    Q_D(JRuleDict);

    //  打开规则文件
    if (!d->openDocument()) {
        return false;
    }

    // 检测规则文件中是否有全局规则，没有则添加
    QDomElement emTable = d->findTableNode(JX);
    if (emTable.isNull()) {
        return false;   // 未找到
    }

    return d->removeSymbol(emTable, name, symbols);
}

bool JRuleDict::addName(const QString &name)
{
    // 检测参数有效性
    if (name.isEmpty()) {
        return false;   // 参数无效
    }

    Q_D(JRuleDict);

    //  打开规则文件
    if (!d->openDocument()) {
        return false;
    }

    // 检测规则文件中是否有全局规则，没有则自动添加
    bool add = false;
    QDomElement emTable = d->findTableNode(&add);
    if (emTable.isNull()) {
        return false;   // 未找到
    }

    // 查找指定别名的节点，没有则自动添加
    add = false;
    QDomElement emItem = d->findItemNode(name, &add);
    if (emItem.isNull() || !add) {
        return false;   // 未找到
    }

    // 保存更改
    if (!d->saveDocument(true)) {
        return false;
    }

    return true;
}

bool JRuleDict::addName(const QString &JX, const QString &name)
{
    // 检测参数有效性
    if (name.isEmpty()) {
        return false;   // 参数无效
    }

    Q_D(JRuleDict);

    //  打开规则文件
    if (!d->openDocument()) {
        return false;
    }

    // 查找指定别名的节点，没有则自动添加
    bool add = false;
    QDomElement emItem = d->findItemNode(JX, name, &add);
    if (emItem.isNull() || !add) {
        return false;   // 未找到
    }

    // 保存更改
    if (!d->saveDocument(true)) {
        return false;
    }

    return true;
}

bool JRuleDict::removeName(const QString &name)
{
    Q_D(JRuleDict);

    //  打开规则文件
    if (!d->openDocument()) {
        return false;
    }

    // 查找全局规则
    QDomElement emTable = d->findTableNode(0);
    if (emTable.isNull()) {
        return false;   // 未找到
    }

    // 查找别名映射节点
    QDomElement emItem = d->findItemNode(emTable, name);
    if (emItem.isNull()) {
        return false;   // 未找到
    }

    // 删除别名映射节点
    emTable.removeChild(emItem);

    // 保存更改
    if (!d->saveDocument(true)) {
        return false;
    }

    return true;
}

bool JRuleDict::removeName(const QString &JX, const QString &name)
{
    Q_D(JRuleDict);

    //  打开规则文件
    if (!d->openDocument()) {
        return false;
    }

    // 查找指定机型的规则
    QDomElement emTable = d->findTableNode(JX);
    if (emTable.isNull()) {
        return false;   // 未找到
    }

    // 查找别名映射节点
    QDomElement emItem = d->findItemNode(emTable, name);
    if (emItem.isNull()) {
        return true;   // 未找到
    }

    // 删除别名映射节点
    emTable.removeChild(emItem);

    // 保存更改
    if (!d->saveDocument(true)) {
        return false;
    }

    return true;
}

bool JRuleDict::existsSymbol(const QString &symbol) const
{
    Q_D(const JRuleDict);
    QMapIterator<QString, QMap<QString, QStringList> > citerRule(d->mapRule);
    while (citerRule.hasNext()) {
        citerRule.next();
        QMapIterator<QString, QStringList> citerNameSymbols(citerRule.value());
        while (citerNameSymbols.hasNext()) {
            citerNameSymbols.next();
            QStringListIterator citerSymbols(citerNameSymbols.value());
            while (citerSymbols.hasNext()) {
                const QString &_symbol = citerSymbols.next();
                if (_symbol == symbol) {
                    return true;
                }
            }
        }
    }

    return false;
}

bool JRuleDict::existsName(const QString &name) const
{
    Q_D(const JRuleDict);
    QMapIterator<QString, QMap<QString, QStringList> > citer(d->mapRule);
    while (citer.hasNext()) {
        citer.next();
        if (citer.value().keys().contains(name)) {
            return true;
        }
    }

    return false;
}

QStringList JRuleDict::allJX() const
{
    Q_D(const JRuleDict);
    return d->mapRule.keys();
}

QStringList JRuleDict::namesOfJX(const QString &JX) const
{
    Q_D(const JRuleDict);
    if (d->mapRule.contains(JX)) {
        return d->mapRule[JX].keys();
    } else {
        return QStringList();
    }
}

QString JRuleDict::nameOfSymbol(const QString &symbol) const
{
    Q_D(const JRuleDict);
    if (!d->mapRule.contains(QString())) {
        return QString::null;
    }

    QMapIterator<QString, QStringList> citerNameSymbols(d->mapRule[QString()]);
    while (citerNameSymbols.hasNext()) {
        citerNameSymbols.next();
        const QStringList &symbols = citerNameSymbols.value();
        if (symbols.contains(symbol)) {
            return citerNameSymbols.key();
        }
    }

    return QString::null;
}

QString JRuleDict::nameOfSymbol(const QString &JX, const QString &symbol) const
{
    Q_D(const JRuleDict);
    if (!d->mapRule.contains(JX)) {
        return QString::null;
    }

    QMapIterator<QString, QStringList> citerNameSymbols(d->mapRule[JX]);
    while (citerNameSymbols.hasNext()) {
        citerNameSymbols.next();
        const QStringList &symbols = citerNameSymbols.value();
        if (symbols.contains(symbol)) {
            return citerNameSymbols.key();
        }
    }

    return QString::null;
}

QString JRuleDict::firstSymbolOfName(const QString &name) const
{
    Q_D(const JRuleDict);
    QMapIterator<QString, QMap<QString, QStringList> > citer(d->mapRule);
    while (citer.hasNext()) {
        citer.next();
        QMapIterator<QString, QStringList> citerNameSymbols(citer.value());
        while (citerNameSymbols.hasNext()) {
            citerNameSymbols.next();
            const QString &_name = citerNameSymbols.key();
            if (_name != name) {
                continue;
            }
            const QStringList &symbols = citerNameSymbols.value();
            if (symbols.isEmpty()) {
                continue;
            }
            return symbols.at(0);
        }
    }

    return QString::null;
}

QStringList JRuleDict::symbolsOfName(const QString &name) const
{
    Q_D(const JRuleDict);
    if (!d->mapRule.contains(QString())) {
        return QStringList();
    }

    const QMap<QString, QStringList> &mapNameSymbols = d->mapRule[QString()];
    if (!mapNameSymbols.contains(name)) {
        return QStringList();
    }

    return mapNameSymbols[name];
}

QStringList JRuleDict::symbolsOfName(const QString &JX, const QString &name) const
{
    Q_D(const JRuleDict);
    if (!d->mapRule.contains(JX)) {
        return QStringList();
    }

    const QMap<QString, QStringList> &mapNameSymbols = d->mapRule[JX];
    if (!mapNameSymbols.contains(name)) {
        return QStringList();
    }

    return mapNameSymbols[name];
}

QString JRuleDict::ruleFilePath() const
{
    Q_D(const JRuleDict);
    return d->filePath;
}

const QMap<QString, QMap<QString, QStringList> > &JRuleDict::data() const
{
    Q_D(const JRuleDict);
    return d->mapRule;
}

bool JRuleDict::replaceJX(const QString &oldJX, const QString &newJX)
{
    Q_D(JRuleDict);

    // 参数有效性检测
    if (oldJX.isEmpty() || newJX.isEmpty()) {
        return false;
    }

    // 打开规则文件
    if (!d->openDocument()) {
        return false;
    }

    // 查找指定机型的规则
    QDomElement emTable = d->findTableNode(oldJX);
    if (emTable.isNull()) {
        return false;   // 未找到
    }

    // 修改机型名称
    emTable.setAttribute("JX", newJX);

    // 保存更改
    if (!d->saveDocument(true)) {
        return false;
    }

    return true;
}

bool JRuleDict::replaceName(const QString &oldName, const QString &newName)
{
    Q_D(JRuleDict);

    // 参数有效性检测
    if (oldName.isEmpty() || newName.isEmpty()) {
        return false;
    }

    // 打开规则文件
    if (!d->openDocument()) {
        return false;
    }

    // 查找全局规则的指定别名节点
    QDomElement emItem = d->findItemNode(oldName);
    if (emItem.isNull()) {
        return false;   // 未找到
    }

    // 修改机型名称
    emItem.setAttribute("name", newName);

    // 保存更改
    if (!d->saveDocument(true)) {
        return false;
    }

    return true;
}

bool JRuleDict::replaceName(const QString &JX, const QString &oldName, const QString &newName)
{
    Q_D(JRuleDict);

    // 参数有效性检测
    if (JX.isEmpty() || oldName.isEmpty() || newName.isEmpty()) {
        return false;
    }

    // 打开规则文件
    if (!d->openDocument()) {
        return false;
    }

    // 查找指定机型的指定别名节点
    QDomElement emItem = d->findItemNode(JX, oldName);
    if (emItem.isNull()) {
        return false;   // 未找到
    }

    // 修改机型名称
    emItem.setAttribute("name", newName);

    // 保存更改
    if (!d->saveDocument(true)) {
        return false;
    }

    return true;
}

bool JRuleDict::replaceSymbol(const QString &name, const QString &oldSymbol, const QString &newSymbol)
{
    Q_D(JRuleDict);

    // 参数有效性检测
    if (name.isEmpty() || oldSymbol.isEmpty() || newSymbol.isEmpty()) {
        return false;
    }

    // 打开规则文件
    if (!d->openDocument()) {
        return false;
    }

    // 查找全局规则下的指定别名节点
    QDomElement emItem = d->findItemNode(name);
    if (emItem.isNull()) {
        return false;   // 未找到
    }

    // 修改
    if (!d->replaceSymbol(emItem, oldSymbol, newSymbol)) {
        return false;   // 修改失败
    }

    return true;
}

bool JRuleDict::replaceSymbol(const QString &JX, const QString &name, const QString &oldSymbol, const QString &newSymbol)
{
    Q_D(JRuleDict);

    // 参数有效性检测
    if (JX.isEmpty() || name.isEmpty() || oldSymbol.isEmpty() || newSymbol.isEmpty()) {
        return false;
    }

    // 打开规则文件
    if (!d->openDocument()) {
        return false;
    }

    // 查找指定机型的指定别名节点
    QDomElement emItem = d->findItemNode(JX, name);
    if (emItem.isNull()) {
        return false;   // 未找到
    }

    // 修改
    if (!d->replaceSymbol(emItem, oldSymbol, newSymbol)) {
        return false;   // 修改失败
    }

    return true;
}
